/*
 * Ex:			
 * File name:   fs.h
 *
 *  Created on: May 21, 2012
 *      Author: ayash
 *
 *
 * Descriptor:
 *
 */

#ifndef FS_H_
#define FS_H_

#include <vector>
#include <sys/types.h>
#include <cassert>

#include "common_defs.h"

using namespace std;

typedef struct
{
	uint num_block_used;
	double avg_block_access;

} file_perf_t;

class FileSystem
{

public:

	FileSystem(unsigned int block_size,
			   unsigned int pointer_size,
	  	  	   unsigned int maximal_size):

	  	  		   _block_size(block_size),
	  	  		   _pointer_size(pointer_size),
	  	  		   _maximal_size(maximal_size)
	{
	}

	virtual ~FileSystem() {}

	result_t calc_performance ( const vector<unsigned int> & fileSizes,
		  	  	  	  	  	  	outputStruct * output )
	{
		result_t result;
		vector<unsigned int>:: const_iterator it;
		file_perf_t file_perf;
		uint size;
		ulong sum_used_blocks = 0;
		ulong num_nonzero_files = 0;
		double sum_avg_access = 0;

		assert( NULL != output );

		for ( it = fileSizes.begin(); it != fileSizes.end(); ++it )
		{
			size = *it;

			if ( size > _maximal_size )
			{
				ERR_PRINT("A file with not supported size was supplied!\n");
				return ERROR_FILE_NOT_SUPPORTED;
			}

			if ( ! size )
			{
				// zero sized file
				sum_used_blocks += 1;

				continue;
			}

			++ num_nonzero_files;
			result = calc_file_perf( size, file_perf );

			if ( OPERATION_SUCCESS != result )
			{
				ERR_PRINT("calc_file_perf() failed with result = %d\n", result);
				return result;
			}

			DBG_PRINT("File: size: %u \t # block used: %u \t avg block access: %lf\n",
					  size,
					  file_perf.num_block_used,
					  file_perf.avg_block_access);

			sum_used_blocks += file_perf.num_block_used;
			sum_avg_access += file_perf.avg_block_access;

		}

		// return the requested numbers
		output->space = sum_used_blocks * _block_size;

		if ( num_nonzero_files )
		{
			output->averageAccessNum = sum_avg_access / num_nonzero_files;
		}
		else
		{
			output->averageAccessNum = 0;
		}


		return OPERATION_SUCCESS;
	}



protected:

	// pure virtual
	virtual result_t calc_file_perf ( uint file_size, file_perf_t & file_perf )		= 0;

	uint _block_size;
	uint _pointer_size;
	uint _maximal_size;
};


#endif /* FS_H_ */
